package com.ssy.lingxi.member.merchant.serviceimpl.base;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ssy.lingxi.common.constant.basic.*;
import com.ssy.lingxi.common.constant.contract.ContractSourceTypeEnum;
import com.ssy.lingxi.common.constant.marketing.ActivityTypeEnum;
import com.ssy.lingxi.common.constant.member.MemberLevelTypeEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderCatetoryAttributeEnum;
import com.ssy.lingxi.common.constant.order.OrderModeEnum;
import com.ssy.lingxi.common.constant.order.OrderSettlementEnum;
import com.ssy.lingxi.common.constant.order.OrderTypeEnum;
import com.ssy.lingxi.common.constant.pay.BalanceTypeEnum;
import com.ssy.lingxi.common.constant.settle.SettlementTypeEnum;
import com.ssy.lingxi.member.merchant.api.constant.*;
import com.ssy.lingxi.member.merchant.api.model.constant.MemberProcessTypeEnum;
import com.ssy.lingxi.member.merchant.entity.*;
import com.ssy.lingxi.member.merchant.model.constant.MemberChannelTypeEnum;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberStringEnum;
import com.ssy.lingxi.member.merchant.repository.*;
import com.ssy.lingxi.member.merchant.service.base.IMemberDataInitService;
import com.ssy.lingxi.member.merchant.service.paas.IBasePaasService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 初始化系统数据
 * @author 万宁
 * @version 2.0.0
 * @date 2021-05-15
 */
@Service
public class MemberDataInitServiceImpl implements IMemberDataInitService {
    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private IBasePaasService basePaasService;

    @Resource
    private MemberTypeRepository memberTypeRepository;

    @Resource
    private RoleTypeRepository roleTypeRepository;

    @Resource
    private ChannelTypeRepository channelTypeRepository;

    @Resource
    private BaseRightConfigRepository baseRightConfigRepository;

    @Resource
    private BaseLevelRuleRepository baseLevelRuleRepository;

    @Resource
    private BaseCreditConfigRepository baseCreditConfigRepository;

    @Resource
    private BasePlatformProcessRepository basePlatformProcessRepository;

    @Resource
    private BaseMemberProcessRepository baseMemberProcessRepository;

    @Resource
    private BaseMemberRuleRepository baseMemberRuleRepository;

    @Resource
    private CountryCodeRepository countryCodeRepository;

    @Resource
    private CountryAreaRepository countryAreaRepository;

    @Resource
    private RoleRepository roleRepository;

    @Resource
    private MemberBusinessTypeRepository memberBusinessTypeRepository;

    /**
     * 初始化系统数据
     */
    @Override
    public void initMemberServiceData() {
        //会员类型
        initMemberType();

        //角色类型
        initRoleType();

        //渠道类型
        initChannelType();

        //基础权益
        initBaseRightConfig();

        //基础升级规则
        initBaseLevelRule();

        //基础信用
        initBaseCreditConfig();

        //初始化平台会员审核流程（会员注册流程）
        initBasePlatformProcess();

        //会员基础流程规则配置
        initBaseMemberProcess();

        //平台规则配置
        initBaseMemberRule();

        //国家编码
        initCountryCode();

        //省市区域
        initCountryArea();

        //创建“平台”角色、会员（由于依赖于其他初始化数据，所以要放在最后创建）
        initPlatformAdmin();

        //2022-02-23在 RoleDO 和 MemberBusinessTypeDO 新增了relType字段，为兼容以前“中文”版本数据，这里做修改
        updateTableNewField();
    }

    /**
     * 在 RoleDO 和 MemberBusinessTypeDO 新增了relType字段，为兼容以前“中文”版本数据，这里做修改
     * @date 2022-02-23
     */
    private void updateTableNewField() {
        Specification<RoleDO> specification = (Specification<RoleDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.isNull(root.get("relType")));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        List<RoleDO> roles = roleRepository.findAll(specification);
        if(!CollectionUtils.isEmpty(roles)) {
            roles.forEach(role -> role.setRelType(role.getRoleName().equals("平台") ? MemberRelationTypeEnum.PLATFORM.getCode() : MemberRelationTypeEnum.OTHER.getCode()));
            roleRepository.saveAll(roles);
        }

        Specification<MemberBusinessTypeDO> businessSpecification = (Specification<MemberBusinessTypeDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.isNull(root.get("relType")));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        List<MemberBusinessTypeDO> businessTypes = memberBusinessTypeRepository.findAll(businessSpecification);
        if(!CollectionUtils.isEmpty(businessTypes)) {
            businessTypes.forEach(businessType -> businessType.setRelType(businessType.getBusinessTypeName().equals("平台运营") ? MemberRelationTypeEnum.PLATFORM.getCode() : MemberRelationTypeEnum.OTHER.getCode()));
            memberBusinessTypeRepository.saveAll(businessTypes);
        }
    }

    /**
     * 初始化会员类型
     */
    private void initMemberType() {
        if(countTable("ms_mc_member_type") > 0) {
            return;
        }

        alterSequence("ms_mc_member_type_seq");

        List<MemberTypeDO> memberTypeList = new ArrayList<>();
        MemberTypeDO memberType = new MemberTypeDO();
        memberType.setTypeEnum(MemberTypeEnum.MERCHANT.getCode());
        memberType.setTypeName(MemberTypeEnum.MERCHANT.getMessage());
        memberTypeList.add(memberType);

        memberType = new MemberTypeDO();
        memberType.setTypeEnum(MemberTypeEnum.MERCHANT_PERSONAL.getCode());
        memberType.setTypeName(MemberTypeEnum.MERCHANT_PERSONAL.getMessage());
        memberTypeList.add(memberType);

        memberType = new MemberTypeDO();
        memberType.setTypeEnum(MemberTypeEnum.CHANNEL.getCode());
        memberType.setTypeName(MemberTypeEnum.CHANNEL.getMessage());
        memberTypeList.add(memberType);

        memberType = new MemberTypeDO();
        memberType.setTypeEnum(MemberTypeEnum.CHANNEL_PERSONAL.getCode());
        memberType.setTypeName(MemberTypeEnum.CHANNEL_PERSONAL.getMessage());
        memberTypeList.add(memberType);

        memberTypeRepository.saveAll(memberTypeList);
    }

    /**
     * 初始化角色类型
     */
    private void initRoleType() {
        if(countTable("ms_mc_role_type") > 0) {
            return;
        }

        alterSequence("ms_mc_role_type_seq");

        List<RoleTypeDO> roleTypeList = new ArrayList<>();
        RoleTypeDO roleType = new RoleTypeDO();
        roleType.setTypeEnum(RoleTypeEnum.SERVICE_PROVIDER.getCode());
        roleType.setRoleTypeName(RoleTypeEnum.SERVICE_PROVIDER.getMessage());
        roleTypeList.add(roleType);

        roleType = new RoleTypeDO();
        roleType.setTypeEnum(RoleTypeEnum.SERVICE_CONSUMER.getCode());
        roleType.setRoleTypeName(RoleTypeEnum.SERVICE_CONSUMER.getMessage());
        roleTypeList.add(roleType);

        roleTypeRepository.saveAll(roleTypeList);
    }

    /**
     * 初始化渠道类型
     */
    private void initChannelType() {
        if(countTable("ms_mc_channel_type") > 0) {
            return;
        }

        alterSequence("ms_mc_channel_type_seq");

        List<ChannelTypeDO> channelTypeList = new ArrayList<>();
        ChannelTypeDO channelType = new ChannelTypeDO();
        channelType.setChannelTypeEnum(MemberChannelTypeEnum.ECOMMERCE.getCode());
        channelType.setName(MemberChannelTypeEnum.ECOMMERCE.getMessage());
        channelTypeList.add(channelType);

        channelType = new ChannelTypeDO();
        channelType.setChannelTypeEnum(MemberChannelTypeEnum.OFFLINE.getCode());
        channelType.setName(MemberChannelTypeEnum.OFFLINE.getMessage());
        channelTypeList.add(channelType);

        channelTypeRepository.saveAll(channelTypeList);
    }

    /**
     * 初始化会员基础权益配置
     */
    private void initBaseRightConfig() {
        if(countTable("ms_mc_base_right_config") > 0) {
            return;
        }

        alterSequence("ms_mc_base_right_config_seq");

        List<BaseRightConfigDO> configList = new ArrayList<>();
        BaseRightConfigDO config = new BaseRightConfigDO();
        config.setAcquireWay(MemberRightAcquireWayEnum.ACQUIRE_BY_TRADE.getMessage());
        config.setAcquireWayEnum(MemberRightAcquireWayEnum.ACQUIRE_BY_TRADE.getCode());
        config.setParamWay(MemberRightParamWayEnum.SET_BY_TRADE_PRICE_RATE.getMessage());
        config.setParamWayEnum(MemberRightParamWayEnum.SET_BY_TRADE_PRICE_RATE.getCode());
        config.setRightTypeEnum(MemberRightTypeEnum.PRICE_RIGHT.getCode());
        config.setName(MemberRightTypeEnum.PRICE_RIGHT.getMessage());
        config.setRemark(MemberRightTypeEnum.PRICE_RIGHT.getRemark());
        config.setStatus(EnableDisableStatus.ENABLE.getCode());
        configList.add(config);

        config = new BaseRightConfigDO();
        config.setAcquireWay(MemberRightAcquireWayEnum.ACQUIRE_BY_TRADE.getMessage());
        config.setAcquireWayEnum(MemberRightAcquireWayEnum.ACQUIRE_BY_TRADE.getCode());
        config.setParamWay(MemberRightParamWayEnum.SET_BY_TRADE_PRICE_RATE.getMessage());
        config.setParamWayEnum(MemberRightParamWayEnum.SET_BY_TRADE_PRICE_RATE.getCode());
        config.setRightTypeEnum(MemberRightTypeEnum.RETURN_MONEY_RIGHT.getCode());
        config.setName(MemberRightTypeEnum.RETURN_MONEY_RIGHT.getMessage());
        config.setRemark(MemberRightTypeEnum.RETURN_MONEY_RIGHT.getRemark());
        config.setStatus(EnableDisableStatus.ENABLE.getCode());
        configList.add(config);

        config = new BaseRightConfigDO();
        config.setAcquireWay(MemberRightAcquireWayEnum.ACQUIRE_BY_TRADE.getMessage());
        config.setAcquireWayEnum(MemberRightAcquireWayEnum.ACQUIRE_BY_TRADE.getCode());
        config.setParamWay(MemberRightParamWayEnum.SET_BY_TRADE_PRICE_RATE.getMessage());
        config.setParamWayEnum(MemberRightParamWayEnum.SET_BY_TRADE_PRICE_RATE.getCode());
        config.setRightTypeEnum(MemberRightTypeEnum.SCORE_POINTS_RIGHT.getCode());
        config.setName(MemberRightTypeEnum.SCORE_POINTS_RIGHT.getMessage());
        config.setRemark(MemberRightTypeEnum.SCORE_POINTS_RIGHT.getRemark());
        config.setStatus(EnableDisableStatus.ENABLE.getCode());
        configList.add(config);
        baseRightConfigRepository.saveAll(configList);
    }

    /**
     * 初始化基础升级规则
     */
    private void initBaseLevelRule() {
        if(countTable("ms_mc_base_level_rule") > 0) {
            return;
        }

        alterSequence("ms_mc_base_level_rule_seq");

        List<BaseLevelRuleDO> ruleList = new ArrayList<>();
        for (MemberLevelRuleTypeEnum levelRuleTypeEnum : MemberLevelRuleTypeEnum.values()) {
            for (MemberLevelTypeEnum memberLevelTypeEnum : MemberLevelTypeEnum.values()) {
                BaseLevelRuleDO rule = new BaseLevelRuleDO();
                rule.setMemberLevelTypeEnum(memberLevelTypeEnum.getCode());
                rule.setMemberLevelTypeName(memberLevelTypeEnum.getMessage());
                rule.setRuleTypeEnum(levelRuleTypeEnum.getCode());
                rule.setRuleName(levelRuleTypeEnum.getMessage());
                rule.setRemark(levelRuleTypeEnum.getRemark());
                rule.setStatus(EnableDisableStatus.ENABLE.getCode());
                ruleList.add(rule);
            }
        }

        baseLevelRuleRepository.saveAll(ruleList);
    }

    /**
     * 初始化会员基础信用
     */
    private void initBaseCreditConfig() {
        if(countTable("ms_mc_base_credit_config") > 0) {
            return;
        }

        alterSequence("ms_mc_base_credit_config_seq");

        List<BaseCreditConfigDO> configList = Arrays.stream(MemberCreditTypeEnum.values()).sorted(Comparator.comparingInt(MemberCreditTypeEnum::getCode)).map(memberCreditTypeEnum -> {
            BaseCreditConfigDO config = new BaseCreditConfigDO();
            config.setCreditTypeName(memberCreditTypeEnum.getName());
            config.setCreditTypeEnum(memberCreditTypeEnum.getCode());
            config.setCreditPoint(memberCreditTypeEnum.getDefaultPoint());
            config.setRemark(memberCreditTypeEnum.getRemark());
            config.setStatus(EnableDisableStatus.ENABLE.getCode());
            return config;
        }).collect(Collectors.toList());

        baseCreditConfigRepository.saveAll(configList);
    }

    /**
     * 初始化平台会员审核流程（会员注册流程）
     */
    private void initBasePlatformProcess() {
        List<BasePlatformProcessDO> platformProcesses = new ArrayList<>();
        BasePlatformProcessDO processDO = new BasePlatformProcessDO();
        processDO.setProcessName(MemberStringEnum.MEMBER_REGISTER_NO_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.PLATFORM_VALIDATION.getCode());
        processDO.setProcessKey("platform_member_directly");
        processDO.setDescription(MemberStringEnum.MEMBER_REGISTER_NO_PROCESS_STEPS.getName());
        processDO.setEmptyProcess(true);
        processDO.setDefaultProcess(false);
        platformProcesses.add(processDO);

        processDO = new BasePlatformProcessDO();
        processDO.setProcessName(MemberStringEnum.MEMBER_REGISTER_CONFIRM_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.PLATFORM_VALIDATION.getCode());
        processDO.setProcessKey("platform_member_verify_confirm");
        processDO.setDescription(MemberStringEnum.MEMBER_REGISTER_CONFIRM_PROCESS_STEPS.getName());
        processDO.setEmptyProcess(false);
        processDO.setDefaultProcess(false);
        platformProcesses.add(processDO);

        processDO = new BasePlatformProcessDO();
        processDO.setProcessName(MemberStringEnum.MEMBER_REGISTER_FULL_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.PLATFORM_VALIDATION.getCode());
        processDO.setProcessKey("platform_member_verify");
        processDO.setDescription(MemberStringEnum.MEMBER_REGISTER_FULL_PROCESS_STEPS.getName());
        processDO.setEmptyProcess(false);
        processDO.setDefaultProcess(true);
        platformProcesses.add(processDO);

        List<BasePlatformProcessDO> basePlatformProcesses = basePlatformProcessRepository.findAll();
        basePlatformProcesses.forEach(process -> platformProcesses.stream().filter(p -> p.getProcessKey().equals(process.getProcessKey())).findFirst().ifPresent(p -> {
            process.setProcessName(p.getProcessName());
            process.setDescription(p.getDescription());
            process.setProcessType(p.getProcessType());
            process.setEmptyProcess(p.getEmptyProcess());
            process.setDefaultProcess(p.getDefaultProcess());
        }));

        basePlatformProcesses.addAll(platformProcesses.stream().filter(p -> basePlatformProcesses.stream().noneMatch(tp -> tp.getProcessKey().equals(p.getProcessKey()))).collect(Collectors.toList()));
        basePlatformProcessRepository.saveAll(basePlatformProcesses);
    }

    /**
     * 初始化基础流程规则配置
     */
    private void initBaseMemberProcess() {
        List<BaseMemberProcessDO> processList = new ArrayList<>();
        //入库流程
        BaseMemberProcessDO processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_depository_directly");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_DEPOSIT_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_DEPOSITORY.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_DEPOSIT_DIRECT_PROCESS_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.DISABLE.getCode());
        processDO.setEmptyProcess(true);
        processList.add(processDO);

        processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_depository_one");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_DEPOSIT_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_DEPOSITORY.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_DEPOSIT_ONE_PROCESS_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.ENABLE.getCode());
        processDO.setEmptyProcess(false);
        processList.add(processDO);

        processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_depository_three");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_DEPOSIT_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_DEPOSITORY.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_DEPOSIT_THREE_PROCESS_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.DISABLE.getCode());
        processDO.setEmptyProcess(false);
        processList.add(processDO);

        processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_depository_four");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_DEPOSIT_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_DEPOSITORY.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_DEPOSIT_FOUR_PROCESS_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.DISABLE.getCode());
        processDO.setEmptyProcess(false);
        processList.add(processDO);

        processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_depository_five");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_DEPOSIT_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_DEPOSITORY.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_DEPOSIT_FIVE_PROCESS_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.DISABLE.getCode());
        processDO.setEmptyProcess(false);
        processList.add(processDO);

        processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_depository_six");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_DEPOSIT_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_DEPOSITORY.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_DEPOSIT_SIX_PROCESS_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.DISABLE.getCode());
        processDO.setEmptyProcess(false);
        processList.add(processDO);

        processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_depository_seven");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_DEPOSIT_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_DEPOSITORY.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_DEPOSIT_SEVEN_PROCESS_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.DISABLE.getCode());
        processDO.setEmptyProcess(false);
        processList.add(processDO);

        //资料变更流程
        processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_detail_update_one");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_CHANGE_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_MODIFICATION.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_INIT_CHANGE_ONE_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.ENABLE.getCode());
        processDO.setEmptyProcess(false);
        processList.add(processDO);

        processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_detail_update_two");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_CHANGE_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_MODIFICATION.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_INIT_CHANGE_TWO_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.DISABLE.getCode());
        processDO.setEmptyProcess(false);
        processList.add(processDO);

        processDO = new BaseMemberProcessDO();
        processDO.setProcessKey("member_detail_update_three");
        processDO.setProcessName(MemberStringEnum.MEMBER_INIT_CHANGE_PROCESS.getName());
        processDO.setProcessType(MemberProcessTypeEnum.MEMBER_MODIFICATION.getCode());
        processDO.setDescription(MemberStringEnum.MEMBER_INIT_CHANGE_THREE_STEPS.getName());
        processDO.setIsDefault(EnableDisableStatus.DISABLE.getCode());
        processDO.setEmptyProcess(false);
        processList.add(processDO);

        List<BaseMemberProcessDO> baseMemberProcesses = baseMemberProcessRepository.findAll();
        baseMemberProcesses.forEach(process -> processList.stream().filter(p -> p.getProcessKey().equals(process.getProcessKey())).findFirst().ifPresent(p -> {
            process.setProcessName(p.getProcessName());
            process.setProcessType(p.getProcessType());
            process.setDescription(p.getDescription());
            process.setIsDefault(p.getIsDefault());
            process.setEmptyProcess(p.getEmptyProcess());
        }));

        baseMemberProcesses.addAll(processList.stream().filter(p -> baseMemberProcesses.stream().noneMatch(tp -> tp.getProcessKey().equals(p.getProcessKey()))).collect(Collectors.toList()));
        baseMemberProcessRepository.saveAll(baseMemberProcesses);
    }

    /**
     * 初始化平台规则配置
     */
    private void initBaseMemberRule() {
        if(countTable("ms_mc_base_member_rule") == 0) {
            alterSequence("ms_mc_base_member_rule_seq");
        }

        List<BaseMemberRuleDO> memberRules = new ArrayList<>();
        //资金归集模式
        memberRules.addAll(Arrays.stream(FundModeEnum.values()).sorted(Comparator.comparingInt(FundModeEnum::getCode)).map(fundMode -> {
            BaseMemberRuleDO memberRule = new BaseMemberRuleDO();
            memberRule.setRuleType(PlatformRuleTypeEnum.FUND.getCode());
            memberRule.setRuleName(PlatformRuleTypeEnum.FUND.getName());
            memberRule.setMethodCode(fundMode.getCode());
            memberRule.setMethodName(fundMode.getName());
            memberRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return memberRule;
        }).collect(Collectors.toList()));

        //库存扣减策略
        memberRules.addAll(Arrays.stream(InventoryReduceTypeEnum.values()).sorted(Comparator.comparingInt(InventoryReduceTypeEnum::getCode)).map(reduceType -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.INVENTORY.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.INVENTORY.getName());
            orderRule.setMethodCode(reduceType.getCode());
            orderRule.setMethodName(reduceType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //下单模式
        memberRules.addAll(Arrays.stream(OrderModeEnum.values()).sorted(Comparator.comparingInt(OrderModeEnum::getCode)).map(orderMode -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.ORDER_MODE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.ORDER_MODE.getName());
            orderRule.setMethodCode(orderMode.getCode());
            orderRule.setMethodName(orderMode.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //订单类型
        memberRules.addAll(Arrays.stream(OrderTypeEnum.values()).sorted(Comparator.comparingInt(OrderTypeEnum::getCode)).map(orderType -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.ORDER_TYPE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.ORDER_TYPE.getName());
            orderRule.setMethodCode(orderType.getCode());
            orderRule.setMethodName(orderType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //营销活动类型
        memberRules.addAll(Arrays.stream(ActivityTypeEnum.values()).filter(e -> !e.getCode().equals(0)).sorted(Comparator.comparingInt(ActivityTypeEnum::getCode)).map(activityType -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.MARKETING.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.MARKETING.getName());
            orderRule.setMethodCode(activityType.getCode());
            orderRule.setMethodName(activityType.getMessage());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //结算方式
        memberRules.addAll(Arrays.stream(OrderSettlementEnum.values()).sorted(Comparator.comparingInt(OrderSettlementEnum::getCode)).map(settlement -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.SETTLEMENT.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.SETTLEMENT.getName());
            orderRule.setMethodCode(settlement.getCode());
            orderRule.setMethodName(settlement.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //品类与属性使用方式
        memberRules.addAll(Arrays.stream(OrderCatetoryAttributeEnum.values()).sorted(Comparator.comparingInt(OrderCatetoryAttributeEnum::getCode)).map(attribute -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.PRODUCT_CATEGORY.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.PRODUCT_CATEGORY.getName());
            orderRule.setMethodCode(attribute.getCode());
            orderRule.setMethodName(attribute.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //采购询源类型
        memberRules.addAll(Arrays.stream(ContractSourceTypeEnum.values()).filter(e -> !e.getCode().equals(0)).sorted(Comparator.comparingInt(ContractSourceTypeEnum::getCode)).map(sourceType -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.PURCHASE_SOURCE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.PURCHASE_SOURCE.getName());
            orderRule.setMethodCode(sourceType.getCode());
            orderRule.setMethodName(sourceType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //采购合同付款方式
        memberRules.addAll(Arrays.stream(PurchaseContractPayTypeEnum.values()).sorted(Comparator.comparingInt(PurchaseContractPayTypeEnum::getCode)).map(contractPayType -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.PURCHASE_CONTRACT.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.PURCHASE_CONTRACT.getName());
            orderRule.setMethodCode(contractPayType.getCode());
            orderRule.setMethodName(contractPayType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //结算支付方式
        memberRules.addAll(Arrays.stream(SettlementTypeEnum.values()).sorted(Comparator.comparingInt(SettlementTypeEnum::getCode)).map(settlementType -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.SETTLEMENT_TYPE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.SETTLEMENT_TYPE.getName());
            orderRule.setMethodCode(settlementType.getCode());
            orderRule.setMethodName(settlementType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //账户余额类型
        memberRules.addAll(Arrays.stream(BalanceTypeEnum.values()).sorted(Comparator.comparingInt(BalanceTypeEnum::getCode)).map(balanceType -> {
            BaseMemberRuleDO orderRule = new BaseMemberRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.BALANCE_TYPE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.BALANCE_TYPE.getName());
            orderRule.setMethodCode(balanceType.getCode());
            orderRule.setMethodName(balanceType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        List<BaseMemberRuleDO> baseMemberRules = baseMemberRuleRepository.findAll();
        baseMemberRules.forEach(baseMemberRule -> memberRules.stream().filter(memberRule -> memberRule.getRuleType().equals(baseMemberRule.getRuleType()) && memberRule.getMethodCode().equals(baseMemberRule.getMethodCode())).findFirst().ifPresent(memberRule -> {
            baseMemberRule.setRuleName(memberRule.getRuleName());
            baseMemberRule.setMethodName(memberRule.getMethodName());
        }));

        baseMemberRules.addAll(memberRules.stream().filter(memberRule -> baseMemberRules.stream().noneMatch(baseMemberRule -> baseMemberRule.getRuleType().equals(memberRule.getRuleType()) && baseMemberRule.getMethodCode().equals(memberRule.getMethodCode()))).collect(Collectors.toList()));
        baseMemberRuleRepository.saveAll(baseMemberRules);
    }

    /**
     * 初始化国家编码
     */
    private void initCountryCode() {
        if(countTable("ms_mc_country_code") > 0) {
            return;
        }

        alterSequence("ms_mc_country_code_seq");

        CountryCodeDO countryCode = new CountryCodeDO();
        countryCode.setCode(CountryCodeEnum.China.getCode());
        countryCode.setTypeEnum(CountryCodeEnum.China.getTypeEnum());
        countryCode.setName(CountryCodeEnum.China.getCn());
        countryCode.setPhoneLength(11);
        countryCodeRepository.saveAndFlush(countryCode);
    }

    /**
     * 初始化省市区域
     */
    private void initCountryArea() {
        try {
            if (countTable("ms_mc_country_area") > 0) {
                return;
            }

            alterSequence("ms_mc_country_area_seq");

            org.springframework.core.io.Resource resource = new ClassPathResource("cn_country_area.json");
            ObjectMapper mapper = new ObjectMapper();
            List<CountryAreaDO> countryAreaList = mapper.readValue(resource.getInputStream(), new TypeReference<List<CountryAreaDO>>() {
            });
            countryAreaList.forEach(area -> area.setId(null));
            countryAreaRepository.saveAll(countryAreaList);
        } catch (Exception e) {
            System.err.println("初始化省市区域表ms_mc_country_area错误:" + e.getMessage());
            System.exit(1);
        }
    }

    private void initPlatformAdmin() {
        if(countTable("ms_mc_member") > 0) {
            return;
        }

        basePaasService.initPlatformAdmin();
    }

    /**
     * 执行 select count(id) from table 语句
     * @param dbTableName 数据库的表名称
     * @return 表数据行数
     */
    private long countTable(String dbTableName) {
        String sql = "select count(id) as total from " + dbTableName + ";";
        SqlRowSet sqlRowSet = jdbcTemplate.queryForRowSet(sql);
        long total = 0;
        while (sqlRowSet.next()) {
            total = sqlRowSet.getLong("total");
        }
        return total;
    }

    /**
     * 更改序列值为1
     * @param sequenceName 序列名称
     */
    private void alterSequence(String sequenceName) {
        String sql = "alter sequence " + sequenceName + " restart with 1";
        jdbcTemplate.execute(sql);
    }
}
